﻿using System;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using Sustainalytics.ClientDW.Synchronization.SyncHbaseData.ExtensionMethods;
using Sustainalytics.Entities.DSO;
using Sustainalytics.Synchronization.Interface;

namespace Sustainalytics.ClientDW.Synchronization.SyncHbaseData
{
    public class SyncHBaseSecurityLists : ISyncStep
    {
        private readonly CDDB.DataConnector.SecurityListRepository _cddb = new CDDB.DataConnector.SecurityListRepository();

        private SyncContext _syncContext;


        public SyncStepOrder ExecutionOrder
        {
            get
            {
                return SyncStepOrder.SyncSecuritiesLists;
            }
        }

        public void Abort()
        {
            throw new NotImplementedException();
        }

        public void Cancel()
        {
            throw new NotImplementedException();
        }

        public SyncContext Start(SyncContext syncContext)
        {
            _syncContext = syncContext;

            var syncDsoData = bool.Parse(ConfigurationManager.AppSettings["SyncDsoDatabase"]);
            if (syncDsoData)
            {
                var dsoConnectionString = _syncContext.DSOConnectionStrings["ClientDW"];

                var respository = new SecuritiesRepository(dsoConnectionString);

                AppendInfoToLog("Cleaning collection");

                respository.CleanCollectionsAsync().Wait();

                this.InsertSecuritiesListAsync(respository).Wait();

                this.AddSecuritiesAssociationsAsync(respository).Wait();
            }

            return this._syncContext;
        }

        private async Task AddSecuritiesAssociationsAsync(SecuritiesRepository respository)
        {
            foreach (var associations in this._cddb.GetSecuritiesAndSecuritiesListAssociations().Batch(1000))
            {
                    await respository.InsertSecurityListSecurityAsssociationAsync(
                        associations.Select(
                            x => x.Map<CDDB.DataConnector.Models.SecuritySecurityListAssociation, SecuritySecurityListsAssociation>())).ConfigureAwait(false);
            }
          
            this.AppendInfoToLog("Finished inserting security securities list associations");
        }

        private async Task InsertSecuritiesListAsync(SecuritiesRepository respository)
        {
            this.AppendInfoToLog("Getting securities list names");

            var securitiesList = this._cddb.GetSecurityLists().ToList();

            this.AppendInfoToLog("Inserting securities list names");

            await respository.InsertSecurityListAsync(
                securitiesList.Select(x => x.Map<CDDB.DataConnector.Models.SecurityList, SecurityList>())).ConfigureAwait(false);

            this.AppendInfoToLog("Inserting securities list constituents");


            foreach (var securityList in securitiesList)
            {
                var constituents = this._cddb.GetSecurityListConstituents(securityList.Id);

                await respository.InsertConstituentsInListAsync(
                    securityList.Id,
                    constituents.Select(s => s.Map<CDDB.DataConnector.Models.SecurityListConstituent, SecurityListConstituent>())).ConfigureAwait(false);
            }

            this.AppendInfoToLog("Finished securities list constituents");
        }

        private void AppendInfoToLog(string info)
        {
            this._syncContext.Log(info);
        }        
    }
}